/*
 * Drunk Js
 * Author    :   Drunk
 * Website   :   http://drunkce.com,  http://idrunk.net
 */

void function(){
var $ = Drunk, jQuery = Drunk ;

Drunk.extend({
	control : function(selecter, config){
		return new Drunk.control.fn.init(selecter, config) ;
	}
}) ;

window.DC = Drunk.control ;
Drunk.control.fn = Drunk.control.prototype ;

Drunk.extend(Drunk.control.fn, {
	init : function(selecter, config){
		var elem = $(selecter) ,
			me = this ;
		
		config = config || elem.attr(Drunk.control.configAttr) ;
		if(!config)return ;

		me.config = config ;
		me.elem = elem ;
		
		me.build() ;
	} ,
	build : function(){
		var me = this , i = 0 ;
		
		me.config = Drunk.control.config(me.config) ;
		// 执行对应的函数
		for(;i<me.config.length;i++){
			try{
				eval("Drunk.control[me.config[i].func](me.elem" +arrayEnArgs(me.config[i].args, "me.config[i].args", 1)+ ")") ;
			}catch(e){
				try{
					eval(me.config[i].func+"(me.elem" +arrayEnArgs(me.config[i].args, "me.config[i].args", 1)+ ")") ;
				}catch(e2){}
			}
		}
	}
}) ;

Drunk.control.fn.init.prototype = Drunk.control.fn ;
Drunk.extend(Drunk.control, {
	cache : {} ,
	endCalls : $.Callbacks() ,
	configAttr : 'drunk' ,
	code : function(elem, code, method){
		// {1:空, 4:错误}
		elem = $(elem) ;
		code = Drunk.int(code) ;
		method = Drunk.int(method) ;
		var codeAttr = 'drunk-code' ,
			oldCode = Drunk.int(elem.attr(codeAttr)),
            val = elem.val().trim();
		
		if(method & 1){
			elem.attr(codeAttr, code | oldCode) ;
		}else if(method & 4){
			elem.attr(codeAttr, (code | oldCode) ^ code) ;
		}else{
            if(val === '' && (code & 1)) return 1;
			return oldCode & code ;
		}
	} ,
	init : function(wrap){
		var wrap = $(wrap || document.body) ,
			controls = wrap.find("["+Drunk.control.configAttr+"]") ,
			elem , config ;

		if(wrap.attr('drunk'))controls = controls.add(wrap) ;
		controls.each(function(index, element) {
			var elem = $(element) ,
				config = elem.attr(Drunk.control.configAttr) ;
			Drunk.control(elem, config) ;
		});
		// 开火
		Drunk.control.endCalls.fire() ;
		Drunk.control.endCalls.empty() ;
		if(!Drunk.control.isCalled && typeof DCCALL !== 'undefined' && Drunk.isFunc(DCCALL)){DCCALL() ;Drunk.control.isCalled = true;}
	} ,
	config : function(config){
		config = config.separate(config.trim()) ;

		var configParseReg = /(\w+)(=([^;]*))?(;|$)/g ,
			configParseMatched = config.string.Match(configParseReg) ,
			i = 0 ,
			configParse = [] ,
			args , j ;

		for(;i<configParseMatched.length;i++){
			configParse[i] = {} ;
			configParse[i].func = configParseMatched[i][1] ;
			// 如果没参数则跳过
			if(!configParseMatched[i][3])continue ;

			// 分割参数
			args = configParseMatched[i][3].Split(',') ;
			for(j = 0;j<args.length;j++){
				// 先将字符串替换回来,再替换引号
				args[j] = args[j].replace(new RegExp(config.partMark + '(\\d+)' + config.markClose, "g"), function($0,$1){
					return config.parts[$1] ;
				}).replace(new RegExp(config.quotationMark + '0' + config.markClose, "g"), "'").replace(new RegExp(config.quotationMark + '1' + config.markClose, "g"), '"') ;
			}
			configParse[i].args = args ;
		}

		return configParse ;
	} ,

	validate : function(elem, notempty, minlen, maxlen, unique, alias, notice, defval, regexp, astplace){
		if(Drunk.empty(alias))return ;
		var elemParent , noticeMark = 'drunk_control_notice';
		elemParent = (elemParent = elem.parent()).is("label,span") ? elemParent : elem;
        if(elem.is('input') && elemParent.is('label')) elemParent = elemParent.parent();
		if(elemParent.parent().find('>span[data-mark='+noticeMark+']').length)return ;
		elem[0].notice = $('<span data-mark="'+noticeMark+'" style="background:left center no-repeat;color:#f00;margin-left:8px;padding:3px 0 3px 24px;">').insertAfter(elemParent) ;

		var isRegexp = Drunk.isReg(regexp = Drunk.objParse(regexp)) ,
			feedback = function(ispass, notice){
				elem[0].notice.css('background-image', 'url('+(Drunk.control.cache.valiconPath || Drunk.local.extpath) + 'images/' + (ispass ? 'right.gif' : 'wrong.png')+')').html(ispass ? '' : notice) ;
				return ispass ;
			} ,
			checksum = function(elem){
				var value = elem.val().trim() ;
				if(value == '')return feedback(Drunk.empty(notempty), alias+' 不能为空！') ;
				if(!Drunk.empty(minlen) && value.length < minlen)return feedback(false, alias+' 不能少于 '+minlen+' 个字符！') ;
				if(!Drunk.empty(maxlen) && value.length > maxlen)return feedback(false, alias+' 不能多于 '+maxlen+' 个字符！') ;
				if(isRegexp && !regexp.test(value))return feedback(false, alias+' 格式错误！'+notice+'，如：'+defval+'。') ;
				if(/!keyword\b/.test(unique) && !Drunk.empty(unique))$.getJSON(unique.replace(/!keyword\b/, value),function(data){feedback(data && data.status, alias+' '+value+' 已存在！')}) ;
				return feedback(true) ;
			} ,
			asterisk ;

		// 必填项提示
		if(notempty && !elem.hasClass('no_drunk_validate_asterisk')){
			astplace = elem.closest('td').prev();
			asterisk = astplace.find('.drunk_validate_asterisk') ;
			asterisk = asterisk.length ? asterisk : $('<span class="drunk_validate_asterisk" style="color:red;">* </span>').prependTo(astplace) ;
		}
		elem.bind('blur', function(evt){checksum($(this)) ;}) ;
	} ,

	hover : function(elem, itemSelecter, onclass, inmethod, outmethod, callback){
		itemSelecter = itemSelecter || '.item' ;
		onclass = onclass || 'on' ;
		inmethod = inmethod || 'mouseover' ;
		outmethod = outmethod || 'mouseout' ;
		callback = callback ? Drunk.objParse(callback) : 0 ;

		var items = elem.find(itemSelecter) ;
		if(!items.length)items = elem.find("ul:first>li") ;

		Drunk.control.hoverBind(items, onclass, inmethod, outmethod, callback) ;
	} ,
	hoverBind : function(items, onclass, inmethod, outmethod, callback){
		var elem ;
		items.each(function(i,e){
			elem = $(e) ;
			elem.bind(inmethod, {'i':i, 'elem':elem}, function(evt){
				evt.data.elem.addClass(onclass) ;
				if(Drunk.isFunc(callback))callback(evt.data.i,items,inmethod) ;
			}).bind(outmethod, {'i':i, 'elem':elem}, function(evt){
				evt.data.elem.removeClass(onclass) ;
				if(Drunk.isFunc(callback))callback(evt.data.i,items,outmethod) ;
			}) ;
		}) ;
	} ,

	// 选项卡
	tab : function(elem, tagSelecter, itemSelecter, onclass, method, initIndex, callback){
		tagSelecter = tagSelecter || '.tag' ;
		itemSelecter = itemSelecter || '.item' ;
		onclass = onclass || 'active' ;
		method = method || 'mouseover' ;
		callback = callback ? Drunk.objParse(callback) : 0 ;

		var tags = elem.find(tagSelecter) ,
			items = elem.find(itemSelecter) ;

		if(!tags.length)tags = elem.find("ul:first>li") ;
		if(itemSelecter != -1 && !items.length)items = elem.find("ul:eq(1)>li") ;

		Drunk.control.tabBind(tags, items, onclass, method, callback) ;
		// 如果有传入索引或者tag有带有激活类标志的tag,否则初始化索引为0,并以这个索引初始化选项卡激活焦点
		tags.filter('.'+onclass+':first').trigger(method).length || tags.eq(initIndex || 0).trigger(method) ;
	} ,
	// 绑定选项卡事件
	tabBind : function(tags, items, onclass, method, callback){
		method = method || 'mouseover' ;
		tags.bind(method, function(){Drunk.control.tabActive(this, tags, items, onclass, callback)}) ;
	} ,
	// 激活选项卡
	tabActive : function(tag, tags, items, onclass, callback){
		var iscurrent ;
		onclass = onclass ? onclass : "active" ;
		tags.each(function(index,element){
			iscurrent = element == tag ;
			if(iscurrent){
				$(element).addClass(onclass) ;
				if(items && items.length)$(items[index]).show() ;
			}else{
				$(element).removeClass(onclass) ;
				if(items && items.length)$(items[index]).hide() ;
			}
			if(Drunk.isFunc(callback))callback(index,tags,items,iscurrent) ;
		}) ;
	} ,

	// 相框
	photo : function(elem,width,height,flag,noadjTop,noadjLeft,callback){
		if(!elem || isNaN(width) || elem[0].D_ADJUSTED)return false;
		var src = elem.attr('src'),
			image = new Image(),
		adjust = function(iW, iH){
			if(!flag){
				if(iW > width){iH = width * iH / iW ;iW = width;}
				if(height && iH > height){iW = height * iW / iH ;iH = height;}
			}else if(flag == 1){
				iH = width * iH / iW ;iW = width;
				if(height && iH < height){iW = height * iW / iH ;iH = height;}
			}

			elem.width(iW).height(iH);
			if(!noadjTop)elem.css('margin-top', (height-iH)/2+"px");
			if(!noadjLeft)elem.css('margin-left', (width-iW)/2+"px");
			elem[0].D_ADJUSTED = 1;
	
			if(Drunk.isFunc(callback))callback({image:elem,width:width,height:height,flag:flag,newWidth:iW,newHeight:iH});
		};
		
		image.src = src;
		var jImage = $(image);

		if(Drunk.ie ? image.readyState == "complete" : image.complete)return adjust(image.width, image.height);
		var div = $('<div style="visibility:hidden;position:absolute;left:0;top:0;width:1px;height:1px;overflow:hidden">').appendTo($(document.body)).append(jImage),
			owidth = image.offsetWidth,
			oheight = image.offsetHeight,
			intervalId,
			check = function (justDo) {
				if(justDo || image.offsetWidth !== owidth || image.offsetHeight !== oheight){
					clearInterval(intervalId);
					jImage.unbind("load");
					justDo ? adjust(image.width, image.height) : adjust(image.offsetWidth, image.offsetHeight);
					return div.remove();
				};
			};
			
		intervalId = setInterval(check, 150);
		jImage.bind('load', function(){check(1)});
	} ,

	// 利SEO优化信息摘要
	summary : function(elem, length, height, unfoldstr, ellipsis, callback){
		if(!Drunk.empty(callback))eval('callback = '+callback+';') ;
		unfoldstr = (unfoldstr ? unfoldstr : "[展开]|[收起]").split("|") ;
		ellipsis = ellipsis || '...' ;
		var unfold = unfoldstr[0] ,
			packup = unfoldstr[1] ,
			content = elem.html() ,
			span = $("<span>").append(content.substr(0,length) + ellipsis) ,
			trigger ;

		if(content.length <= length)return ;

		span.content = content ;

		trigger = $("<span>", {'class': 'drunk_summary_tag',html : unfold, style : 'cursor:pointer;'}).bind("click",function(){
			if(!this.unfold){
				this.unfold = true ;
				elem.height("auto");
				$(this).addClass('drunk_summary_tag_on') ;
				span.html(span.content) ;
				trigger.html(packup) ;
			}else{
				this.unfold = false ;
				elem.height(height);
				$(this).removeClass('drunk_summary_tag_on') ;
				span.html(span.content.substr(0,length) + ellipsis) ;
				trigger.html(unfold) ;
			}
			if(Drunk.isFunction(callback))callback(this.unfold, elem) ;
			return false ;
		}) ;

		elem.empty().append(span).append(trigger) ;
	} ,

	// 输入框及默认值
	input : function(elem, type, value, color){
		// 输入框
		var regs = {
				'num' : [/^\d+$/, /[^\d]/g] ,
				'eng' : [/^[a-z]+$/i, /[^a-z]/ig] ,
				'wd' : [/^\w+$/, /[^\w]/g] ,
				'sin' : [/^[x00-xff]+$/, /[^[^x00-xff]]/g]
			} ,
		upfunc = function(evt){
			var val = elem.val() ;
			// 如果按下的非字符输入键,则不反应
			if(evt.which && !Drunk.isValkey(evt.which))return ;

			if(!regs[type][0].test(val)){
				elem.val(val.replace(regs[type][1], '')) ;
			}
		} ;

		if(regs[type]){elem.bind('keyup', upfunc).bind('blur', upfunc);}

		// 如果未设置默认值则返回
		if(typeof value === "undefined" || value === "")return ;
		// 默认值
		color = color || '#999' ;
		var defcolor = elem.css('color') ;

		elem.bind("focus", function(){
			var inval = elem.val() ;
			if(inval == value)elem.val("").css("color", defcolor) ;
			Drunk.control.code(elem, 1, 4) ;
		}).bind("blur", function(){
			var inval = elem.val() ;
			if(inval == ""){
				elem.val(value).css("color", color) ;
				Drunk.control.code(elem, 1, 1) ;
			}
		}).trigger('blur') ;
	} ,

	// 调整高度
	height : function(elem, adjElem, feature, height){
		// 如果未初始化对象,则初始化
		var heightData = Drunk.control.cache.heightData ,
			heightSize = {'win':$(window).height()} ;
		// 如果缓存数据未初始化,初始化之
		if(!$.isPlainObject(heightData))heightData = Drunk.control.cache.heightData = {} ;

		// 如果无特征码,特征码之
		feature = feature || 'fs6U*yuklu' ;
		var current = heightData[feature] ;
		// 如果当前特征数据未初始化,初始化之
		if(!$.isPlainObject(current)){
			current = heightData[feature] = {} ;
			current.args = [] ;
		}

		// 如果传入的是高度宏,则替换宏变量为值
		if(!Drunk.empty(height)){
			if(height == 'follow'){
				current.follow = {'wrap':elem, 'trigger':adjElem} ;
			}else{
				current.height = Drunk.isInt(height) ? height : Drunk.int(heightSize[height]) ;
			}
		}
		current.args[current.args.length] = [elem, adjElem] ;

		if(!Drunk.control.endCalls.has(Drunk.control.heightCall))Drunk.control.endCalls.add(Drunk.control.heightCall) ;
	} ,

	// 高度调整初始化回调
	heightCall : function(){
		window.setTimeout(function(){
			var heightData = Drunk.control.cache.heightData , i , current ;
			for(i in heightData){
				current = heightData[i] ;
				eval('Drunk.control.heightSame(current, ' + arrayEnArgs(current.args, 'current.args') + ')') ;
			}
		},300) ;
	} ,

	// 高度调整静态方法
	heightSame : function(){
		var elements = [], i = 0, warpHeight, maxheight = 0, wrap, Item, adjustItem, args = [] ;
		for(var j=0;j<arguments.length;j++){args[j] = arguments[j] ;}
		
		var current = $.isPlainObject(args[0]) ? args.shift() : {} ;
		maxheight = Drunk.int(current.height) ;

		for(;i<args.length;i++){
			Item = $.isArray(args[i]) ? args[i] : [args[i]] ;

			wrap = $(Item[0]) ;
			adjustItem = Item.length && Item[1] ? wrap.find(Item[1]) : wrap ;

			warpHeight = wrap.outerHeight() ;
			adjustItemHeight = adjustItem.height() ;

			if(warpHeight > maxheight)maxheight = warpHeight ;
			elements[elements.length] = [adjustItem, warpHeight, adjustItemHeight] ;
		}
		if(current.follow){
			if(!current.follow.adjusted){
				current.follow.adjusted = 1 ;
				current.follow.initial = maxheight ;
			}else{
				wrapHeight = current.follow.wrap.height() ;
				maxheight = wrapHeight > current.follow.initial ? wrapHeight : current.follow.initial ;
			}
		}
		
		for(i=0;i<elements.length;i++){
			if(elements[i][1] === maxheight)continue ;
			elements[i][0].height(elements[i][2] + maxheight - elements[i][1]) ;
		}
	} ,
	
	keywords : function(elem, words, classname){
		classname = classname || "highlight" ;
		var reg, text, currentMatches, originalTextSplit, originalSplitPart , tmpTextNode , tmpSpanNode ;
		reg = new RegExp(words.replace(/(['"])([^\s\1]*\s[^\1]*)\1/g, function($0, $1, $2){return $2.replace(/\s/g, "&nbsp:")}).replace(/\s+/g, "|").replace(/&nbsp:/g, " "), "g") ;
		elem.traversal(3, function(textNode){
			text = textNode.nodeValue.trim() ;
			if(text === "")return ;
			
			currentMatches = text.match(reg) ;
			if(!currentMatches)return ;
			originalTextSplit = text.split(reg) ;
			
			for(var i=0;i<originalTextSplit.length;i++){
				originalSplitPart = originalTextSplit[i] ;
				if(originalSplitPart !== ""){
					tmpTextNode = document.createTextNode(originalSplitPart) ;
					textNode.parentNode.insertBefore(tmpTextNode, textNode) ;
				}
				if(currentMatches.length > i){
					tmpSpanNode = document.createElement("span") ;
					tmpSpanNode.className = classname ;
					tmpSpanNode.innerHTML = currentMatches[i] ;
					textNode.parentNode.insertBefore(tmpSpanNode, textNode) ;
				}
			}

			textNode.parentNode.removeChild(textNode) ;
		}) ;
	} ,

	simplified : function(elem, tochs, chs, cht){
		if(!chs || !cht)return ;
		chs = Drunk.objParse(chs) ;
		cht = Drunk.objParse(cht) ;
		if(tochs){var _chs = chs;chs = cht;cht = _chs;}
		var text, textLength, i, newText, currentChar, chsIndex, tmpTextNode ;
	
		elem.traversal(3, function(textNode){
			text = textNode.nodeValue ,
			textLength = text.length ,
			i = 0 ,	newText = '' ;
	
			for(;i<textLength;i++){
				currentChar = text.substr(i, 1) ;
				if(currentChar && (chsIndex = chs.indexOf(currentChar)) != -1)currentChar = cht.substr(chsIndex, 1) ;
				newText += currentChar ;
			}
	
			tmpTextNode = document.createTextNode(newText) ;
			textNode.parentNode.insertBefore(tmpTextNode, textNode) ;
			textNode.parentNode.removeChild(textNode) ;
		}) ;
	} ,

	// 多条控件
	multi : function(elem, config){
		return new Drunk.control.multi.prototype.init(elem, config) ;
	} ,
	
	// 无限级分类
	'class' : function(elem, config){
		return new Drunk.control['class'].prototype.init(elem,config) ;
	}
}) ;

var arrayEnArgs = function(array, arrayName, comma){
	if(typeof array === "undefined")return '' ;
	var i = 0 , args = [] ;
	for(;i<array.length;i++){
		args[i] = arrayName + "["+ i +"]" ;
	}
	return (comma && array.length ? ", " : "") + args.join() ;
}




/***           multi control           ***/

$.extend(Drunk.control.multi.prototype, {
	init : function(elem, config){
		config = $.isPlainObject(config) ? config : {} ;
		var me = this , i ;

		me.conf = {
			// 是否单个
			bachelor : false ,
			// 属性表
			character : {'url':'文件地址', 'title':'标题', 'memo':'描述', 'sequence':'排序'} ,
			// 需要列表显示的字段,如果位与1,则a标签之,如果位与2,则tooltip之,64:列表隐藏,128:dialog隐藏
			fields : {'url': 3, 'title': 66, 'sequence' : 2} ,
			// 上限数
			countLimit : 0 ,
			ctrlstr : '操作' ,
			wrap : '<table>' ,
			thead : '<thead>' ,
			tbody : '<tbody>' ,
			listItem : '<tr>' ,
			column : '<td>' ,
			control : '<em>' ,
			controls : {
				"编辑" : me.edit,
                                " | "  : me.str,
				"删除" : me.remove
			} ,
			afterItemSet : Drunk.control.multi.afterItemSet
		} ;
		// 取字段键名表
		$.extend(me.conf, config) ;
		
		me.elem = $(elem).hide() ;
		me.foundation() ;
		me.add(me.conf.items) ;
        me.structure();
		me.root[0].obj = me ;
	} ,

    // 建基
	foundation : function(){
		var me = this;
		me.conf.colkeys = Drunk.objarray(me.conf.fields, 1) ;
        if(!me.conf.items) me.conf.items = me.elem.val();

		me.wrap = $(me.conf.wrap).insertAfter(me.elem) ;
		me.root = $(me.conf.tbody).appendTo(me.wrap) ;
		me.items = [] ;

		me.available = me.root.length && me.elem.length ;
		if(!me.available)return false ;
	} ,

    // 调整列表结构
    structure : function(){
        var me = this, i=0, j = 1, tds;
            hasitems = me.root.children('tr').length;

        if(hasitems){
            if(!me.thead){
                me.thead = $(me.conf.thead).insertBefore(me.root);
                for(;i<me.conf.colkeys.length;i++){
                    if(me.conf.fields[me.conf.colkeys[i]] & 64) continue ;		// 列表隐藏
                    if((tds = me.root.find('tr td:nth-child('+j+')')) && D.empty(tds.text())){ // 删除空列
                        me.conf.fields[me.conf.colkeys[i]] |= 64;
                        tds.remove(); // 这里有隐性bug, 当有新记录插入表时, 如果之前对列作了删除操作, 但新的数据却非空, 那么就错位了, 标准做法应该不能基于dom做判断, 而是记录数据, 比较蛋疼先养着
                        continue;
                    }
                    $(me.conf.column,{'text':me.conf.character[me.conf.colkeys[i]]}).appendTo(me.thead); // 插入表头
                    j ++;
                }
                $(me.conf.column,{'text':me.conf.ctrlstr}).appendTo(me.thead); // 插入操作标签
            }
        }else if(me.thead){
            me.thead.remove();
            delete me.thead;
        }
    },

	add : function(items){
		var me = this , i = 0 ;

		if(items && typeof items === "string"){
			items = items.trim() ;
			try{items = $.parseJSON(items);}catch(e){} ;
			if(!$.isArray(items))items = String(items).Split(';') ;
		}

		if(!$.isArray(items))items = [items] ;

		if(!me.available)return false ;

		// 文件数量限制
		if(me.items && me.items.length >= 1){
			// 单文件模式
			if(me.conf.bachelor)return alert('您已经上传了文件,如需修改请点击文件名右边的编辑!') ;
			if(me.conf.countLimit && me.items.length + items.length > me.conf.countLimit){
				var overflow = me.items.length + items.length - me.conf.countLimit ;
				items.splice(items.length - overflow - 1) ;
				alert('最多允许'+me.conf.countLimit+'项，您超出了'+overflow+'项，超出部分将被自动截掉！') ;
			}
		}

		for(;i<items.length;i++)me.set(items[i]) ;
	} ,

	set : function(data, index){
		var me = this ,
			i = 0 , j, listItem , columnText , column , columnContent , controlWarp ;

		if(!me.available || Drunk.empty(data))return false ;

		if(!$.isPlainObject(data)){
			if(!$.isArray(data))data = String(data).Split(",") ;
			data = Drunk.objObj(data, me.conf.colkeys, true) ;
		}

		// 当前项在所有项目中的索引,如果有则为编辑更新,如果没有则为数组长度
		if(Drunk.isInt(index) && index >= 0){
			// 更新操作
			listItem = me.root.find("tr:eq("+index+")") ;
			controlWarp = listItem.children('.controls') ;
			// 删除老的
			listItem.children().not(controlWarp).remove() ;
		}else{
			listItem = $(me.conf.listItem).appendTo(me.root) ;
			index = me.items.length ;
			listItem[0].index = index ;
			
			controlWarp = $(me.conf.column, {'class' : 'controls'}).appendTo(listItem) ;
			// 插入控件
			for(j in me.conf.controls)$(me.conf.control, {'style': 'cursor:pointer;', 'text' : j}).appendTo(controlWarp).bind('click', {'obj':me, 'listItem': listItem}, me.conf.controls[j]) ;
		}

		for(j in me.conf.fields){
			if(me.conf.fields[j] & 64)continue ;		// 列表隐藏
			columnText = data[j] || '' ;
			// 是否新窗口超链接
			columnContent = $("<p>").append((me.conf.fields[j] & 1) ? $('<a>', {'href' : columnText, 'target' : '_blank' , 'text': D.empty(data.title) ? columnText : data.title /* 蛋疼链接扩展, 先就这么着用吧 */}) : columnText) ;
			// 是否tooltip提示
			if(me.conf.fields[j] & 2)columnContent.attr('tooltip', '') ;
			// 插入到控件容器之前
			column = $(me.conf.column).append(columnContent).insertBefore(controlWarp) ;
		}
		// 字段插入回调
		if(Drunk.isFunc(me.conf.afterItemSet))me.conf.afterItemSet(me, listItem) ;

		me.items[index] = data ;

		me.sync() ;
	} ,

	edit : function(evt){
		Drunk.control.multi.edit(evt.data.obj, evt.data.listItem, evt.data.listItem[0].index) ;
	} ,

	remove : function(evt){
		Drunk.control.multi.remove(evt.data.obj, evt.data.listItem, evt.data.listItem[0].index) ;
	},

	sync : function(){
		var me = this ;

		// 是否单文件模式
		me.elem.val(me.conf.bachelor ? (me.items[0] ? me.items[0].url : '') : Drunk.dump(me.items)).trigger('change') ;
        me.structure(); // 重构列表结构
	},

	dataMove : function(){
		var me = this ;
		// 更新索引
		me.root.find('tr').each(function(i, e) {
            e.index = i ;
        });
	}
}) ;

$.extend(Drunk.control.multi, {
	afterItemSet : function(obj, tr){
		// 挂载tooltip
		Drunk.control.multi.tooltip(obj, tr) ;
	} ,
	edit : function(obj, listItem, index){
		Drunk.control.multi.dialog(obj, index) ;

		Drunk.control.multi.editor.dialog('open') ;
	} ,
	// 编辑保存
	save : function(obj){
		var editor = Drunk.control.multi.editor ,
			data = {} , elem, name 
			index = editor[0].index ;

		editor.find("[name]").each(function(i, e){
			elem = $(e) ;
			name = elem.attr("name") ;
			data[name] = elem.val() ;
		}) ;

		// 更新同步数据
		obj.set(data, index) ;
		editor.dialog("close");
	} ,
	remove : function(obj, listItem, index){
		listItem.remove() ;
		obj.items.splice(index, 1) ;
		// 修正绑定的索引数据
		obj.dataMove() ;
		obj.sync() ;
	} ,
	tooltip : function(obj, elem){
		elem.tooltip({
			items : '[tooltip]' ,
			content : function(){
				var current = $(this) ,
					Item = obj.items[elem[0].index] ,
					currentText = current.has('a') ? current.find('a').attr('href') : current.text() ,
					ext = currentText.path('extension') ,
					content = '<table><tbody>' , i ;

				for(i in obj.conf.character){
					if(Drunk.isUndef(Item[i]))continue ;
					content += '<tr><th style="width:72px;font-weight:400;text-align:right;vertical-align:top;">' + obj.conf.character[i] + '：</th><td style="word-break:break-all;word-wrap:break-word;vertical-align:top;">' + Item[i] + '</td></tr>' ;
				}
				// 显示图片
				if(/^(bmp|gif|jpeg|jpg|png)$/i.test(ext))content += '<tr><td colspan="2"><img src="'+currentText+'" onload="Drunk.control.photo($(this), 290,290,0,1)" /></td></tr>' ;
				
				content += '</tbody></table>'
				return content ;
			}
		}) ;
	} ,
	
	// 编辑框
	dialog : function(obj, index){
		// 如果已经创建过dialog,则只进行赋值
		if(Drunk.control.multi.editor){
			 Drunk.control.multi.editor.find("[name]").each(function(i, e){
				elem = $(e) ;
				name = elem.attr("name") ;
				elem.val(obj.items[index][name] || '') ;
			}) ;
			// 记录索引
			Drunk.control.multi.editor[0].index = index ;
			Drunk.control.multi.editor[0].obj = obj ;
			return ;
		}
		var table = $('<table title="编辑文件信息"><tbody></tbody></table>') , elem, i, input, value, tr ;
		for(i in obj.conf.character){
			value = obj.items[index][i] || '' ;
			// dialog隐藏
			if(obj.conf.fields[i] & 128){input = $('<input type="hidden" name="'+i+'" value="'+value+'">').appendTo(table) ;continue ;}
			// 赋予原始值
			input = i === 'memo' ? $('<textarea name="'+i+'">').val(value) : $('<input name="'+i+'">').val(value) ;
			tr = $('<tr><th style="width:72px;font-weight:400;text-align:right;">' + obj.conf.character[i] + '：</th><td></td></tr>') ;
			tr.children("td:last").append(input) ;
			table.append(tr) ;
			if(Drunk.isFunc(obj.conf.editorCall))obj.conf.editorCall(input, i) ;
		}
		table.appendTo(document.body)[0].index = index ;
		table[0].obj = obj ;
		table.dialog({
			autoOpen: false, height: 300, width: 350, modal: true,
			buttons : {
				'确定' : function(){
					Drunk.control.multi.save(this.obj) ;
				} , '取消' : function(){
					$(this).dialog("close") ;
				}
			}
		}) ;
		Drunk.control.multi.editor = table ;
	}
}) ;

Drunk.control.multi.prototype.init.prototype = Drunk.control.multi.prototype ;
window.DCM = Drunk.control.multi ;


/* class control */

Drunk.extend(Drunk.control['class'].prototype , {
	init : function(elem , config){
		var me = this ;

		me.wrap = $(elem) ;
		me.conf = {
			type : 'select' ,
			// 记录值的元素名,如果有定义则记录
			elemName : 0 ,
			// 记录结构的元素名,如果有定义则记录
			structName : 0 ,
			// 载入级别数
			topLevel : 0 ,
			deftext : '请选择' ,
			// 初始选中值
			defval : 0 ,
			delimiter : '>' ,
			// 根值
			rootId : 1
		} ;
		me.cache = {} ;
		me.classes = [] ;

		if(Drunk.isUsefulObj(config))$.extend(me.conf, config) ;

		// 初始化记录值的元素
		if(me.conf.elemName)me.elem = $('<input>', {'type':'hidden', 'name':me.conf.elemName}).appendTo(me.wrap) ;
		if(me.conf.structName){
            me.struct = $('[name=' +me.conf.structName+ ']');
            if(!me.struct.length) me.struct = $('<input>', {'type':'hidden', 'name':me.conf.structName}).appendTo(me.wrap) ;
        }

		// 初始化数据
		me.dataInit(me.conf.data) ;
		if(me.conf.defval){
			me.defvalStruct = me.getStruct(me.conf.defval).Split(me.conf.delimiter) ;
			me.defvalStruct.shift() ;
		}

		// 初始化事件
		if(me.conf.change){
			if(!Drunk.isFunc(me.conf.change)){me.conf.change = Drunk.objParse(me.conf.change) ;}
			if(Drunk.isFunc(me.conf.change))me.change = me.conf.change ;
			delete me.conf.change ;
		}

		me.build(me.conf.rootId) ;
	} ,
	dataInit : function(data){
		var me = this, i = 0, isInit = false, itemData;
		if(!$.isArray(me.data)){me.data = [] ;isInit = true;}
		if(Drunk.empty(data) && !isInit)return false ;

		for(;i<data.length;i++){
            itemData = Drunk.objObj(data[i], ['id', 'cid', 'title', 'structure']); // 排重
            if(D.objSearch(me.data, itemData['id'], ['id']) === -1) me.data[me.data.length] = itemData;
        }
		if(isInit){
			paDataCheck = D.objSearch(me.data, me.conf.rootId, ['id']) ;
			if(paDataCheck == -1){me.data.unshift({id:me.conf.rootId, cid:0}) ;}
			delete me.conf.data ;
		}
    } ,
	load : function(cid){
		var me = this ;
		me.cache[cid] = 1 ;
		$.ajax({
			url		: me.conf.src.replace(/!id/gi, cid) ,
			cache	: false ,
			success	: function(data){
				me.dataInit(data) ;
				me.build(cid) ;
			}
		}) ;
	} ,
	build : function(cid){
		if(Drunk.empty(cid))return false ;
		var me = this , paData ,
		data = D.objSearch(me.data, cid, ['cid'], 1) ;

		// 如果无下级数据,或者数据级别已到达所限制的级别,则返回
		if(me.conf.topLevel && me.classes.length >= me.conf.topLevel)return false ;

		// 如果是异步模式,并且未开启缓存,或者未加载过缓存数据,则异步加载
		if(me.conf.src && Drunk.empty(data) && Drunk.isUndef(me.cache[cid]))return me.load(cid) ;

		// 当前触发事件的元素源数据
		paData = Drunk.objSearch(me.data, cid, ['id'], 1)[0] ;

		if(!$.isArray(data) || !data.length)return false ;
		if(me.conf.deftext)data.unshift({id:cid,title:me.conf.deftext});
		me['build' + me.conf.type.ucfirst()](data, paData) ;
	} ,
	buildSelect : function(data, paData){
		var me = this , i = 0 ,	
			option ,select , defaultVal , value ;

		select = $('<select>').appendTo(me.wrap) ;
		me.classes[me.classes.length] = [paData, select] ;

		for(;i<data.length;i++){option = $('<option>', {'value':data[i].id, 'text':data[i].title}).appendTo(select) ;}
		// 初始化初始值
		if($.isArray(me.defvalStruct) && me.defvalStruct.length >= me.classes.length){
			select.val(me.defvalStruct[me.classes.length - 1]) ;
			delete me.defvalStruct[me.classes.length - 1] ;
		}

		select.bind('change', {obj : me, paid : paData.id}, function(evt){
            value = this.value ;
			if(evt.data.obj.change)evt.data.obj.change(value) ;
			evt.data.obj.sync(value) ;
			// 清除该父ID下所有其他内容
			evt.data.obj.clear(evt.data.paid) ;
			// 如果当前选择值等于其父级分类ID,则表示选择的是默认项,那么不进行分类创建操作
			if(value != evt.data.paid)evt.data.obj.build(value) ;
		// 如果未载入到初始值,则递归创建
		}).trigger('change') ;
	} ,
	getStruct : function(id, full, cache){
		var me = this ,
			paData = Drunk.objSearch(me.data, id, ['id'], 1)[0] ;

		if(!paData)return '' ;
		if(paData.cid && paData.id != me.conf.rootId)return me.getStruct(paData.cid, full, paData.cid + me.conf.delimiter + (cache || id)) ;

		var struct = String(cache || id) ;
		return full && paData.structure ? paData.structure + me.conf.delimiter + struct : struct ;
	} ,
	// 清除就控件及数据,需在当前项创建之前调用,不然会影响当前创建
	clear : function(cid){
		var me = this , i , index ,
			sibling = Drunk.objSearch(me.classes, cid, [0,'cid'], 1) ;

		for(i=sibling.length-1;i>=0;i--){
			// 找出当前项在记录集中的索引
			index = Drunk.objSearch(me.classes, sibling[i][0].id, [0,'id']) ;
			me.classes[index][1].remove() ;
			me.classes.splice(index, 1) ;

			// 递归清除子数据
			me.clear(sibling[i][0]['id']) ;
		}
	} ,
	sync : function(value){
		var me = this , curData ;
		if(me.elem)me.elem.val(value).trigger('change') ;
		if(me.struct && value){
			curData = Drunk.objSearch(me.data, value, ['id'], 1)[0] ;
			me.struct.val(curData.structure || '1>') ;
		}
	}
}) ;


Drunk.control['class'].prototype.init.prototype = Drunk.control['class'].prototype ;
window.DCC = Drunk.control['class'] ;

$(function(){Drunk.control.init();});
}() ;